/**
 * 
 */

package com.wutianyi.maven.plugins;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.VelocityEngine;

import com.wutianyi.maven.properties.ConfigProperties;
import com.wutianyi.maven.xml.ParserXmlDom4j;

/**
 * @author wutianyi
 * @goal autoconfig_compile
 */
public class AutoConfigCompileMojo extends AbstractMojo
{

    private static Logger logger = Logger.getLogger(AutoConfigCompileMojo.class);
    /**
     * 定义config的模式，是开发还是线上
     * 
     * @parameter expression="${autoconfig.mode}" default-value="develop"
     */
    private String mode;

    /**
     * config xml 文件的地址
     * 
     * @parameter expression="${autoconfig.config_xml_path}"
     *            default-value="autoconfig.xml"
     * 
     */
    private String configXmlPath;

    /**
     * config properties 文件存放的路径
     * 
     * @parameter expression="${autoconfig.config_properties_path}"
     */
    private String configPropertiesPath;

    /**
     * 当定义加载资源的方式为文件方式的时候，需要指定到那个目录下去加载文件 如果制定加载方式为file但是没有制定，则会初始化为当前用户跟目录下
     * 
     * @parameter expression="${autoconfig.resource_load_path}"
     */
    private String resourceLoadPath;

    private VelocityEngine velocityEngine;
    private ParserXmlDom4j config;
    private ConfigProperties properties;
    private VelocityContext context;

    private static final String rootPath = System.getProperty("user.dir");
    private static final String resourcePath = System.getProperty("user.dir") + File.separator + "src" + File.separator
            + "main" + File.separator + "resources" + File.separator + "META-INF";
    private static final String outputPath = System.getProperty("user.dir") + File.separator + "src" + File.separator
            + "main" + File.separator + "resources";

    @Override
    public void execute() throws MojoExecutionException, MojoFailureException
    {

        logger.info("[The user dir:] " + System.getProperty("user.dir"));
        logger.info("[The Classpath:]" + this.getClass().getResource("").getFile());
        logger.info(mode);
        logger.info(this.configPropertiesPath);
        logger.info(this.configXmlPath);
        logger.info(this.resourceLoadPath);
        logger.info("[Begin init!]");
        init();
        logger.info("[End init!]");
        logger.info("[Begin MergeTemplate!]");
        mergeTemplate();
        logger.info("[End MergeTemplate!]");

        destroy();
    }

    /**
     * 关闭资源
     */
    private void destroy()
    {

        logger.info("[Rewrite The Properties!]");
        if (null != properties)
        {
            properties.close();
        }
        logger.info("[End Rewrite The Properties!]");
    }

    /**
     * 渲染模板
     */
    private void mergeTemplate()
    {

        Map<String, String> generatorFiles = config.getGeneratorFiles();

        if (null == generatorFiles)
        {
            return;
        }

        for (Entry<String, String> entry : generatorFiles.entrySet())
        {
            logger.info("[Begin merge vm ]" + entry.getKey());
            Template template = velocityEngine.getTemplate(entry.getKey(), "utf8");
            if (null == template)
            {
                continue;
            }
            PrintWriter pw = null;

            try
            {
                File outputFile = new File(outputPath, entry.getValue());
                boolean result = outputFile.getParentFile().mkdirs();
                if (result)
                {
                    logger.info("Make The Directory: " + outputFile.getParent());
                }
                pw = new PrintWriter(outputFile.getAbsolutePath(), "utf8");
                template.merge(context, pw);
            }
            catch (FileNotFoundException e)
            {
                e.printStackTrace();
            }
            catch (UnsupportedEncodingException e)
            {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            finally
            {
                if (pw != null)
                {

                    pw.close();
                }
            }
            logger.info("[End merge vm ]" + entry.getKey());
        }
    }

    /**
     * 根据相应的配置项进行初始化
     */
    private void init()
    {

        // testInitOtherParameter();
        velocityEngine = new VelocityEngine();
        if (StringUtils.isBlank(resourceLoadPath))
        {
            // 如果选择了以文件的方式进行文件加载，但是又没有制定path，则默认到根目录
            resourceLoadPath = resourcePath;
        }
        else
        {
            resourceLoadPath = rootPath + File.separator + resourceLoadPath;
        }
        velocityEngine.setProperty(VelocityEngine.FILE_RESOURCE_LOADER_PATH, resourceLoadPath);
        // else {
        // velocityEngine.setProperty("file.resource.loader.class",
        // "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
        // }
        if (StringUtils.isBlank(configXmlPath))
        {

            config = new ParserXmlDom4j(resourcePath + File.separator + configXmlPath, true);
        }
        else
        {
            config = new ParserXmlDom4j(rootPath + File.separator + configXmlPath, true);
        }
        if (StringUtils.isBlank(configPropertiesPath))
        {
            properties = new ConfigProperties();
        }
        else
        {
            properties = new ConfigProperties(configPropertiesPath);
        }
        initContext();
    }

    /**
     * 初始化context中的变量的值
     */
    private void initContext()
    {

        context = new VelocityContext();
        context.put("mode", mode);

        Map<String, String> propertiesDefines = config.getProperties();
        Map<String, String> decriptions = config.getDescriptions();

        if (null == propertiesDefines)
        {
            return;
        }

        for (Entry<String, String> entry : propertiesDefines.entrySet())
        {
            String key = entry.getKey();
            String defaultValue = entry.getValue();
            String description = decriptions.get(key);
            String value = properties.getProperties(key, defaultValue, description);
            context.put(key, value);
        }
    }

    public String getMode()
    {
        return mode;
    }

    public void setMode(String mode)
    {
        this.mode = mode;
    }

    public String getConfigXmlPath()
    {
        return configXmlPath;
    }

    public void setConfigXmlPath(String configXmlPath)
    {
        this.configXmlPath = configXmlPath;
    }

    public String getConfigPropertiesPath()
    {
        return configPropertiesPath;
    }

    public void setConfigPropertiesPath(String configPropertiesPath)
    {
        this.configPropertiesPath = configPropertiesPath;
    }

    public String getResourceLoadPath()
    {
        return resourceLoadPath;
    }

    public void setResourceLoadPath(String resourceLoadPath)
    {
        this.resourceLoadPath = resourceLoadPath;
    }

    public static void main(String[] args) throws MojoExecutionException, MojoFailureException
    {

        // System.out.println(resourcePath + File.separator + configXmlPath);
    }
}
